<?php    
    class mail_model extends Model
    {
        //mailing model, handling mail functions
        private $mailFunctional;
        private $pop3Functional;
        private $templateReady = false;
        private $template;
        private $mailSendingConnected = false;
        private $mailReceivingConnected = false;
        private $templateParsed = false;
        private $variables = array();
        private $username = null;
        private $password = null;
        private $smtpServer = null;
        private $smtpPort = null;
        private $pop3Server = null;
        private $mailSendingConnection = null;
        private $mailReceivingConnection = null;
        
        public function __construct($username = null, $password = null){
            include(SYS_CONFIG . '/mail.php');
            
            parent::__construct();
            $this->load->library('mail');
            $this->mailFunctional = new MAIL();
            $this->pop3Functional = new POP3();
            
            if (!empty($username)){
                $this->username = $username;
            }
            else{
                $this->username =  $mailOptions['username'];
            }
            if (!empty($password)){
                $this->password = $password;
            }
            else{
                $this->password = $mailOptions['password'];
            }
            
            $this->_init();
        }
        
        public function __destruct(){
            $this->close();
        }
        
        public function setOptions($options = array()){
            foreach($options as $key => $value){
                if (property_exists($this, $key)){
                    $this->{$key} = $value;
                }
            }
        }
        
        public function loadTemplate($templateName = null){
            $this->templateReady = true;
            
            if (empty($templateName)){
                //no template
                $this->template = '{content}';
            }
            elseif (!file_exists(SYS_PUBLIC . "/email${templateName}.php")){
                //no template file exist
                $this->template = null;
                $this->templateReady = false;
            }
            else{
                //template file loading
                $this->template = file_get_contents(SYS_PUBLIC . "/email/${templateName}.php");
            }
            
            $this->templateParsed = false;
            return;
        }
        
        public function assignVar($variables = array()){
            if (empty($variables)){
                return;
            }
            else{
                $this->variables = array_merge($this->variables, $variables);
            }
        }
        
        public function clearVar(){
            $this->variables = array();
        }
        
        public function getEmail(){
            if (!$this->mailReceivingConnected)
                if(!$this->_doConnectReceiving())
                    return null;
            return $this->_doGet();
        }
        
        public function sendEmail($topic, $content, $to = array()){
            //required loadTemplate
            if (!$this->templateReady) 
                $this->loadTemplate();
            //template loaded
            if (!$this->mailSendingConnected)
                if (!$this->_doConnectSending())
                    return false;
            return $this->_doSend($topic, $content, $to);
        }
        
        public function close(){
            if ($this->mailSendingConnected)
                $this->_doDisConnectSending();
            if ($this->mailReceivingConnected)
                $this->_doDisConnectReceiving();
        }
        
        private function _doConnectSending(){
            if (!$this->mailSendingConnected){
                if (empty($this->username) ||
                    empty($this->password) ||
                    empty($this->smtpServer) ||
                    empty($this->smtpPort)){
                        return false;
                    }
                $this->mailSendingConnection = 
                    $this->mailFunctional->connect(
                        $this->smtpServer,
                        $this->smtpPort,
                        $this->username,
                        $this->password
                    );
                if (false === $this->mailSendingConnection)
                    return false;
                else{
                    //connected
                    $this->mailSendingConnected = true;
                }
                return true;
            }
        }
        
        private function _doConnectReceiving(){
            if (!$this->mailReceivingConnected){
                if (empty($this->username) ||
                    empty($this->password) ||
                    empty($this->pop3Server)){
                        return false;
                    }
                $this->mailReceivingConnection = 
                    $this->pop3Functional->connect(
                        $this->pop3Server,
                        $this->username,
                        $this->password
                    );
                if (false === $this->mailReceivingConnection){
                    return false;
                }
                else{
                    //connected
                    $this->mailReceivingConnected = true;
                }
                return true;
            }
        }
        
        private function _doDisConnectSending(){
            if ($this->mailSendingConnected){
                $this->mailFunctional->disconnect($this->mailSendingConnection);
                $this->mailSendingConnection = null;
                $this->mailSendingConnected = false;
                $this->mailFunctional->delto();
            }
        }
        
        private function _doDisConnectReceiving(){
            if ($this->mailReceivingConnected){
                $this->pop3Functional->disconnect($this->mailReceivingConnection);
                $this->mailReceivingConnection = null;
                $this->mailReceivingConnected = false;
            }
        }
        
        private function _doSend($topic, $content, $to){
            if (empty($to)){
                return false;
            }
            if (!is_array($to)){
                $to = array($to);
            }
            foreach($to as $recv){
                $this->mailFunctional->addto($recv);
            }
            $this->variables = array_merge($this->variables, array('content' => $content));
            if (!$this->templateParsed)
                $this->_doParseTemplate();
            //parse complete, sending mail
            $this->mailFunctional->subject($topic);
            $this->mailFunctional->html($this->template);
            $this->mailFunctional->from($this->username);
            return $this->mailFunctional->send($this->mailSendingConnection);
        }
        
        private function _doGet(){
            //get emails
            $state = $this->pop3Functional->pstat($this->mailReceivingConnection);
            if (!$state) return false;
            $retVal = null;
            list($cnt) = array_keys($state);
            if ($cnt > 0){
                //have message
                $retVal = $this->pop3Functional->pretr($this->mailReceivingConnection, $cnt);
            }
            return $this->_parseEmail($retVal);
        }
        
        public function _parseEmail($mail){
            throw new Exception("Not implemented!");
            //TODO parsing email by part
            //future release features
        }
        
        private function _doParseTemplate(){
            if (!$this->templateReady)
                $this->loadTemplate();
            //parsing
            $parsingFunc = create_function('$varname, &$var', 'return isset($var[$varname]) ? $var[$varname] : null;');
            $this->template = preg_replace('/{(.+?)}/uie', '$parsingFunc("\1", $this->variables)', $this->template);
            $this->templateParsed = true;
        }
        
        private function _init(){
            include(SYS_CONFIG . '/mail.php');
            
            if (count($mailOptions) < 2)
                return;
            
            $info = array_slice($mailOptions, 2);
            foreach($info as $key => &$value){
                if (property_exists($this, $key)){
                    $this->{$key} = $value;
                }
            }
        }
    }